'require tools.dnsrecordhandlers as drh';
var callHostHints, callDUIDHints, callDHCPLeases, CBILeaseStatus, CBILease6Status;
+var checkUfpInstalled, callUfpList;
callHostHints = rpc.declare({
object: 'luci-rpc',
expect: { '': {} }
});
+checkUfpInstalled = rpc.declare({
+ object: 'file',
+ method: 'stat',
+ params: [ 'path' ]
+});
+
+callUfpList = rpc.declare({
+ object: 'fingerprint',
+ method: 'fingerprint',
+ expect: { '': {} }
+});
+
CBILeaseStatus = form.DummyValue.extend({
renderWidget: function(section_id, option_id, cfgvalue) {
return E([
return view.extend({
load: function() {
return Promise.all([
- callHostHints(),
- callDUIDHints(),
- getDHCPPools(),
- network.getNetworks(),
- uci.load('firewall')
- ]);
+ checkUfpInstalled('/usr/sbin/ufpd')
+ ]).then(data => {
+ var promises = [
+ callHostHints(),
+ callDUIDHints(),
+ getDHCPPools(),
+ network.getNetworks(),
+ data[0].type === 'file' ? callUfpList() : null,
+ uci.load('firewall')
+ ]
+
+ return Promise.all(promises);
+ });
},
render: function(hosts_duids_pools) {
duids = hosts_duids_pools[1],
pools = hosts_duids_pools[2],
networks = hosts_duids_pools[3],
+ macdata = hosts_duids_pools[4],
m, s, o, ss, so, dnss;
let noi18nstrings = {
so.rmempty = true;
so.cfgvalue = function(section) {
var macs = uci.get('dhcp', section, 'mac');
+ var formattedMacs;
+ var hint, entry;
+
if(!Array.isArray(macs)){
- return expandAndFormatMAC(L.toArray(macs));
+ formattedMacs = expandAndFormatMAC(L.toArray(macs));
} else {
- return expandAndFormatMAC(macs);
+ formattedMacs = expandAndFormatMAC(macs);
+ }
+
+ if (!macdata) {
+ return formattedMacs;
}
+
+
+ if (Array.isArray(formattedMacs)){
+ for (let mac in formattedMacs) {
+ entry = formattedMacs[mac].toLowerCase();
+ if (macdata[entry]) {
+ hint = macdata[entry].vendor ? macdata[entry].vendor : null;
+ formattedMacs[mac] += ` (${hint})`;
+ }
+ }
+ return formattedMacs;
+ }
+
+ if (formattedMacs) {
+ entry = formattedMacs[0].toLowerCase();
+ hint = macdata[entry].vendor ? macdata[entry].vendor : null;
+ formattedMacs[0] += ` (${hint})`;
+ }
+ return formattedMacs;
};
//removed jows renderwidget function which hindered multi-mac entry
so.validate = validateMACAddr.bind(so, pools);
Object.keys(hosts).forEach(function(mac) {
- var hint = hosts[mac].name || L.toArray(hosts[mac].ipaddrs || hosts[mac].ipv4)[0];
+ var vendor;
+ var lower_mac = mac.toLowerCase();
+ if (macdata)
+ vendor = macdata[lower_mac] ? macdata[lower_mac].vendor : null;
+ const hint = vendor || hosts[mac].name || L.toArray(hosts[mac].ipaddrs || hosts[mac].ipv4)[0];
so.value(mac, hint ? '%s (%s)'.format(mac, hint) : mac);
});
cbi_update_table(mapEl.querySelector('#lease_status_table'),
leases.map(function(lease) {
var exp;
+ var vendor;
if (lease.expires === false)
exp = E('em', _('unlimited'));
else
exp = '%t'.format(lease.expires);
+ for (let mac in macdata) {
+ if (mac.toUpperCase() === lease.macaddr) {
+ vendor = macdata[mac].vendor ?
+ ` (${macdata[mac].vendor})` : null;
+ }
+ }
+
var hint = lease.macaddr ? hosts[lease.macaddr] : null,
name = hint ? hint.name : null,
host = null;
return [
host || '-',
lease.ipaddr,
- lease.macaddr,
+ vendor ? lease.macaddr + vendor : lease.macaddr,
exp
];
}),
expect: { interface: [] }
});
+var checkUfpInstalled = rpc.declare({
+ object: 'file',
+ method: 'stat',
+ params: [ 'path' ]
+});
+
+var callUfpList = rpc.declare({
+ object: 'fingerprint',
+ method: 'fingerprint',
+ expect: { '': {} }
+});
+
function applyMask(addr, mask, v6) {
var words = v6 ? validation.parseIPv6(addr) : validation.parseIPv4(addr);
var bword = v6 ? 0xffff : 0xff;
return view.extend({
load: function() {
return Promise.all([
- callNetworkInterfaceDump(),
- L.resolveDefault(fs.exec('/sbin/ip', [ '-4', 'neigh', 'show' ]), {}),
- L.resolveDefault(fs.exec('/sbin/ip', [ '-4', 'route', 'show', 'table', 'all' ]), {}),
- L.resolveDefault(fs.exec('/sbin/ip', [ '-4', 'rule', 'show' ]), {}),
- L.resolveDefault(fs.exec('/sbin/ip', [ '-6', 'neigh', 'show' ]), {}),
- L.resolveDefault(fs.exec('/sbin/ip', [ '-6', 'route', 'show', 'table', 'all' ]), {}),
- L.resolveDefault(fs.exec('/sbin/ip', [ '-6', 'rule', 'show' ]), {})
- ]);
+ checkUfpInstalled('/usr/sbin/ufpd')
+ ]).then(data => {
+ var promises = [
+ callNetworkInterfaceDump(),
+ L.resolveDefault(fs.exec('/sbin/ip', [ '-4', 'neigh', 'show' ]), {}),
+ L.resolveDefault(fs.exec('/sbin/ip', [ '-4', 'route', 'show', 'table', 'all' ]), {}),
+ L.resolveDefault(fs.exec('/sbin/ip', [ '-4', 'rule', 'show' ]), {}),
+ L.resolveDefault(fs.exec('/sbin/ip', [ '-6', 'neigh', 'show' ]), {}),
+ L.resolveDefault(fs.exec('/sbin/ip', [ '-6', 'route', 'show', 'table', 'all' ]), {}),
+ L.resolveDefault(fs.exec('/sbin/ip', [ '-6', 'rule', 'show' ]), {}),
+ data[0].type === 'file' ? callUfpList() : null
+ ];
+
+ return Promise.all(promises);
+ });
},
getNetworkByDevice(networks, dev, addr, mask, v6) {
return matching_iface;
},
- parseNeigh: function(s, networks, v6) {
+ parseNeigh: function(s, macs, networks, v6) {
var lines = s.trim().split(/\n/),
res = [];
var m = lines[i].match(/^([0-9a-f:.]+) (.+) (\S+) *$/),
addr = m ? m[1] : null,
flags = m ? m[2].trim().split(/\s+/) : [],
- state = (m ? m[3] : null) || 'FAILED';
+ state = (m ? m[3] : null) || 'FAILED',
+ vendor;
if (!addr || state == 'FAILED' || addr.match(/^fe[89a-f][0-9a-f]:/))
continue;
if (!flags.lladdr)
continue;
+
+ for (let mac in macs) {
+ if (flags.lladdr === mac)
+ vendor = macs[mac].vendor;
+ }
var net = this.getNetworkByDevice(networks, flags.dev, addr, v6 ? 128 : 32, v6);
res.push([
addr,
- flags.lladdr.toUpperCase(),
+ vendor ? flags.lladdr.toUpperCase() + ` (${vendor})` : flags.lladdr.toUpperCase(),
E('span', { 'class': 'ifacebadge' }, [ net ? net : '(%s)'.format(flags.dev) ])
]);
}
return res;
},
- parseRoute: function(s, networks, v6) {
+ parseRoute: function(s, macs, networks, v6) {
var lines = s.trim().split(/\n/),
res = [];
ip4rule = data[3].stdout || '',
ip6neigh = data[4].stdout || '',
ip6route = data[5].stdout || '',
- ip6rule = data[6].stdout || '';
+ ip6rule = data[6].stdout || '',
+ macdata = data[7];
var device_title = _('Which is used to access this %s').format(_('Target'));
var target_title = _('Network and its mask that define the size of the destination');
])
]);
- cbi_update_table(neigh4tbl, this.parseNeigh(ip4neigh, networks, false),
+ cbi_update_table(neigh4tbl, this.parseNeigh(ip4neigh, macdata, networks, false),
E('em', _('No entries available'))
);
cbi_update_table(route4tbl, this.parseRoute(ip4route, networks, false),
cbi_update_table(rule4tbl, this.parseRule(ip4rule, networks, false),
E('em', _('No entries available'))
);
- cbi_update_table(neigh6tbl, this.parseNeigh(ip6neigh, networks, true),
+ cbi_update_table(neigh6tbl, this.parseNeigh(ip6neigh, macdata, networks, true),
E('em', _('No entries available'))
);
cbi_update_table(route6tbl, this.parseRoute(ip6route, networks, true),